#include "ggear_filestream.h"

namespace ggear
{
	namespace io
	{
		FileStream::FileStream(const glb::String& _path, FileStream::FileAccessMode _mode)
			: mFile(null), mSize(0), mMode(0)
		{
			if(!_path.Length()) return;

		#if defined(WIN32)
			switch(_mode)
			{
			case FileAccessMode_Read:
				mFile = _wfopen(_path.Chars(), L"rb"); break;
			
			case FileAccessMode_Write:
				mFile = _wfopen(_path.Chars(), L"wb"); break;

			case FileAccessMode_Append:
				mFile = _wfopen(_path.Chars(), L"ab"); break;

			case FileAccessMode_ReadEx:
				mFile = _wfopen(_path.Chars(), L"rb+"); break;

			case FileAcessMode_WriteEx:
				mFile = _wfopen(_path.Chars(), L"wb+"); break;

			case FileAccessMode_AppendEx:
				mFile = _wfopen(_path.Chars(), L"ab+"); break;

			default: return;
			}
		#endif

			if(isnull(mFile)) return;

			mMode = _mode;
			
			// Get file size
			fseek(mFile, 0, SEEK_END);
			mSize = ftell(mFile);
			fseek(mFile, 0, SEEK_SET);
		}


		FileStream::~FileStream()
		{
			Close();
		}


		u32 FileStream::Size()
		{
			return mSize;
		}

		u32 FileStream::Position()
		{
			return (u32)ftell(mFile);
		}


		u32 FileStream::Read(u32 _size, u8* _dst)
		{
			if(!_size || isnull(_dst) || isnull(mFile) 
			|| !(mMode & FileAccessMode_Read))
				return 0;
			return (u32)fread(_dst, 1, _size, mFile);
		}


		u32 FileStream::Write(u32 _size, u8* _src)
		{
			if(!_size || isnull(_src) || isnull(mFile) 
			|| !(mMode > FileAccessMode_Read))
				return 0;
			return (u32)fwrite(_src, 1, _size, mFile);
		}


		u32 FileStream::Seek(u32 _offset, b8 _fromBeg /* = false */)
		{
			if(isnull(mFile)) return 0;

			u32 res = 0;
			if(_fromBeg)
				res = (u32) fseek(mFile, _offset, SEEK_SET);
			else
				res = (u32) fseek(mFile, _offset, SEEK_CUR);
			
			return res;
		}


		void FileStream::Close()
		{
			if(!isnull(mFile))
			{
				if(!fclose(mFile))
				{
					mFile = null;
				}
			}
			mSize = 0;
		}
	}
}